"use strict";

var shortId = require('shortid'),
    stackTrace = require('stack-trace'),
    _ = require('underscore'),
    path = require('path'),
    Misc = require('./utils/misc');

/**
 * @module Helpers
 * @summary Helper functions for some common tasks.
 */
module.exports = {
    /**
     * Create an event emitter. Previously, use a 3rd party, now change to node.js builtin.
     * @method
     * @return {EventEmitter} An event emitter
     */
    createEventEmitter: function () {
        var EventEmitter = require('events').EventEmitter;
        return new EventEmitter();
    },

    /**
     * Create a random string.
     * @method
     * @param {object} options
     * @param {int} [options.length=8] - Length of the generated string
     * @param {boolean} [options.numeric=true] - Include numerics or not
     * @param {boolean} [options.letters=true] - Include letters or not
     * @param {boolean} [options.special=false] - Include special characters or not
     * @return {string} A random string
     */
    randomString: require('random-string'),

    /**
     * Create a request object.
     * @method
     * @return {object} A request object
     */
    request: require('request'),

    /**
     * Hash the given object via crc32.
     * @method
     * @param {Object} object - The object to be hashed
     * @return {String}
     */

    crc32Hash: function (object) {
        var crc32 = require('buffer-crc32');
        return crc32.signed(JSON.stringify(object));
    },

    /**
     * Create a unique (in-process) short id.
     * @method
     * @return {string} A short id
     */
    getShortId: function () { return shortId.generate(); },

    /**
     * Create a timestamp integer as the number of millisecond since midnight January 1, 1970 UTC.
     * @method
     * @return {string} A timestamp
     */
    timestamp: function () { return (new Date()).valueOf(); },

    /**
     * Create a stack traces.
     * @method
     * @param {int} [skip = 1] - How many stacks to skip
     * @param {int} [length = 10] - How many stacks to trace
     * @returns {string} Callstack dumps
     */
    callstack: function (skip, length) {
        skip || (skip = 1);
        length || (length = 10);

        var app = require('./app'),
            sites = stackTrace.get().slice(skip, skip+length);
        return _.reduce(sites, function (result, site) {
            return result + '  ' + (site.getFunctionName() || 'anonymous') + '() in file "' +
                path.relative(app.root, site.getFileName()) +
                '" at line [' + site.getLineNumber() + ']\n';
        }, '');
    },

    /**
     * Write a system log.
     * @method
     * @param {int} level - Log level, e.g., error, warn, info, verbose, debug
     * @param {string} message - Message
     * @param {*} meta - Any extra meta data
     */
    syslog: function (level, message, meta) {
        var app = require('./app.js');
        app.log(level, message, meta);
    },

    /**
     * Connect to a db with nodeframe database service.
     * @method
     * @param {string} db - Db token, syntax: "db":"connection key", e.g. "mongodb:connection1".
     * @param {connectDbCallback} cb
     */
    connectDb: function (db, cb) {
        var app = require('./app.js'),
            parts = db.split(':', 2),
            dbmsService = app.$[parts[0]];

        dbmsService.connect(parts[1], cb);
    },

    /**
     * Get the db connection string
     * @method
     * @param {string} db - Db token, syntax: "db":"connection key", e.g. "mongodb:connection1".
     * @returns {string} The connection string
     */
    connStr: function (db) {
        var app = require('./app.js'),
            parts = db.split(':', 2),
            dbmsService = app.$[parts[0]];

        return dbmsService.connStr(parts[1]);
    },

    /**
     * Cache an object in memory with or without expiry.
     * @method
     * @param {object} data - The object to cache
     * @param {int} [seconds] - TTL in seconds, i.e. time to live
     * @returns {string} The key of the cached data
     */
    cacheObject: function (data, seconds) {
        var Cache = require('./utils/objectcache');
        return Cache.default.push(data, seconds);
    },

    /**
     * Get and remove an object in memory cache by key.
     * @method
     * @param {string} key - The key of the object to pop out
     * @returns {*} The cached object
     */
    popObject: function (key) {
        var Cache = require('./utils/objectcache');
        return Cache.default.pop(key);
    },

    /**
     * Render  a swig-style string.
     * @param {string} template - Template string
     * @param {object} [context] - Context to render with
     * @returns {string}
     */
    renderSwig: function (template, context) {
        var swig = require('swig');
        return swig.render(template, { locals: context });
    }
};

/**
 * The database connection callback
 *
 * @callback connectDbCallback
 * @param {Db} db - The database connection object
 */
